﻿//Copyright (c) 2009, Andreas Grünwald
//All rights reserved.

#if !SILVERLIGHT

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Timers;
using yaTDL.Core.Properties;


namespace yaTDL.Core
{
    /// <summary>
    /// A class that will, once initialized,regularly back up a indicated file. (.net-only, no Silverlight-support)
    /// </summary>
    public class BackupService:Service
    {
        string fileName;

        static string filePrefix { get { return ApplicationSettings.Settings.Backup_FilePrefix; } }
        static string filePrefix_legacy = "TaskStore_Backup_";  //the filePrefix used in earlier versions of yaTDL. Files with that prefix will also be included when cleaning up backups.

        static ApplicationSettings Settings = ApplicationSettings.Settings;
        
        
          
        /// <summary>
        /// Initializes a new instance of BackupService.
        /// </summary>
        /// <param name="fileName">The full path of the file that will be backed up.</param>
        public BackupService(string fileName):base()
        {
            this.fileName = fileName;

            #if DEBUG           //set the BackupDirectory for Debug-Mode to the debug application directory
            Settings.Backup_BackupDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\yaTDL_Debug\Backup\";
            Settings.Save();
            #endif

            Settings.Backup_LastBackup = DateTime.Now;
            Settings.Save("Backup_LastBackup");



            Settings.PropertyChanged += new PropertyChangedEventHandler(Settings_PropertyChanged);


            if (DateTime.Now > Settings.Backup_LastBackup.Add(Settings.Backup_Interval))
            {
                timer.Interval = 1000;
            }
            else
            {
                double interval = (DateTime.Now - Settings.Backup_LastBackup.Add(Settings.Backup_Interval)).TotalMilliseconds;
                if (interval > 0)
                {
                    timer.Interval = interval;
                }
            }

            timer.Enabled = Settings.Backup_Enable;
                 
        }


        /// <summary>
        /// Does necessary actions if a Setting realted backups has been changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Settings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {       
            switch (e.PropertyName)
            {
                case "Backup_BackupDirectory":
                    if (String.IsNullOrEmpty(Settings.Backup_BackupDirectory))
                    {
                        Settings.Backup_BackupDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\yaTDL\Backup\";
                        Settings.Save("Backup_BackupDirectory");
                    }
                    break;
                case "Backup_LastBackup":
                    if (Settings.Backup_LastBackup == null)
                    {
                        Settings.Backup_LastBackup = DateTime.Now;
                        Settings.Save("Backup_LastBackup");
                    }
                    timer.Stop();                    
                    double interval = (Settings.Backup_LastBackup.AddMilliseconds(Settings.Backup_Interval.TotalMilliseconds) - DateTime.Now).TotalMilliseconds;
                    timer.Interval = interval > 0 ? interval : 5000;
                    timer.Enabled = Settings.Backup_Enable;
                    break;
                case "Backup_Enable":
                case "Backup_Interval":
                    timer.Stop();
                    double _interval = (Settings.Backup_LastBackup.AddMilliseconds(Settings.Backup_Interval.TotalMilliseconds) - DateTime.Now).TotalMilliseconds;
                    timer.Interval = _interval > 0 ? _interval : 5000;
                    timer.Enabled = Settings.Backup_Enable;
                    break;
            }            
        }

        protected override void DoAction()
        {
            runBackup();
        }

        /// <summary>
        /// Backs up the current version of the file.
        /// </summary>
        private void runBackup()
        {
            if (!Directory.Exists(Settings.Backup_BackupDirectory))
            {
                try
                {
                    createDirectory(Settings.Backup_BackupDirectory);
                }
                catch (Exception)
                {
                    Settings.Backup_BackupDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\yaTDL\Backup\";
                    Settings.Save();
                    runBackup();
                    return;
                }
                
            }

            if (!File.Exists(fileName)) { return; }


            try
            {
                File.Copy(fileName, Path.Combine(Settings.Backup_BackupDirectory, filePrefix + DateTime.Now.ToString().Replace(":", "-") + Path.GetExtension(fileName)));
            }
            catch (Exception)
            {
                timer.Stop();
                timer.Interval = 60000;
                timer.Start();
                return;                
            }

            removeOldFiles();

            Settings.Backup_LastBackup = DateTime.Now;
            timer.Stop();
            timer.Interval = Settings.Backup_Interval.TotalMilliseconds;
            timer.Start();
            Settings.Save();

        }

        /// <summary>
        /// Cleans up the backup-directory.
        /// If there are more backups in the directory than specified in the settings, they will be deleted.
        /// </summary>
        static void removeOldFiles()
        {
            if (Settings.Backup_Count < 0 || Settings.Backup_KeepAll) { return; }

            //get all files that are yaTDL backups. (Includieng backups created by earlier versions of yaTDL that start with the prefix specified by filePrefix_legacy)
            List<String> files = Directory.GetFiles(Settings.Backup_BackupDirectory, filePrefix + "*").Union<string>(Directory.GetFiles(Settings.Backup_BackupDirectory, filePrefix_legacy + "*")).OrderByDescending(x => File.GetCreationTime(x)).ToList<string>();
            
            for (int i = Settings.Backup_Count; i < files.Count; i++)
            {
                try
                {
                    File.Delete(files[i]);
                }
                catch (Exception)
                { }
            }
        }


        /// <summary>
        /// Creates the indicated directory.
        /// This will also word, if the parent directories of the new directory don't exist either.
        /// </summary>
        /// <param name="path"></param>
        static void createDirectory(string path)
        {          

            string directory = path;
            int levelsToCreate = 0;

            while (!Directory.Exists(directory))
            {
                directory = Path.GetDirectoryName(directory);
                levelsToCreate += 1;
            }

            while (levelsToCreate > 0)
            {
                string nextDirectory = path;
                for (int i = levelsToCreate; i > 1; i--)
                {
                    nextDirectory = Path.GetDirectoryName(nextDirectory);
                }
                Directory.CreateDirectory(nextDirectory);
                levelsToCreate -= 1;

            }
        }

    }

   
}


#endif